#pragma once
#include <iostream>
#include <pthread.h>
#include <vector>
#include <queue>
#include <unistd.h>
#define NUMPTHREAD 5
#define NUMTASK 5
using namespace std;
template <class T>
class pthreadPool
{
public:
    pthreadPool(int nump = NUMPTHREAD, int numt = NUMTASK) : _numpthread_t(nump), _numtask(numt)
    {
        pthread_cond_init(&_full, nullptr);
        pthread_cond_init(&_empty, nullptr);
        pthread_mutex_init(&_mtx, nullptr);
        pthread_spin_init(&_spin, PTHREAD_PROCESS_SHARED);
    }
    static void *enter(void *args)
    {
        pthreadPool<T> *sp = reinterpret_cast<pthreadPool *>(args);
        pthread_spin_lock(&sp->_spin);
        cout << "线程" << endl;
        //sleep(10);
        sp->_pthread_t.push_back(pthread_self());
        pthread_spin_unlock(&sp->_spin);
        while (true)
        {
            T ret;
            cout << "进入任务" << endl;
            sp->pop(ret);
            // 处理任务
            cout << "处理任务" << endl;
            cout << ret << endl;
        }
    }
    void start()
    {
        pthread_t tid[_numpthread_t];
        for (size_t i = 0; i < _numpthread_t; i++)
        {
            pthread_create(tid + i, nullptr, enter, this);
        }
    }
    void pop(T &x)
    {
        pthread_mutex_lock(&_mtx);
        while (_task.size() == 0)
        {
            pthread_cond_signal(&_full);
            pthread_cond_wait(&_empty, &_mtx);
        }
        x = _task.front();
        cout << "取到任务" << endl;
        _task.pop();
        cout << pthread_self() << endl;
        sleep(1);
        pthread_mutex_unlock(&_mtx);
    }
    void task1(const T &x)
    {
        pthread_mutex_lock(&_mtx);
        while (_task.size() == _numtask)
        {
            pthread_cond_signal(&_empty);
            pthread_cond_wait(&_full, &_mtx);
        }
        _task.push(x);
        cout << "插入完成" << endl;
        pthread_mutex_unlock(&_mtx);
    }
    ~pthreadPool()
    {
        pthread_spin_destroy(&_spin);
        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_full);
        pthread_cond_destroy(&_empty);
        for (auto &e : _pthread_t)
            pthread_join(e, nullptr);
    }

private:
    vector<pthread_t> _pthread_t;
    queue<T> _task;
    int _numpthread_t;
    int _numtask;
    // 自旋锁
    pthread_spinlock_t _spin;
    pthread_mutex_t _mtx;
    // 条件变量
    pthread_cond_t _full;
    pthread_cond_t _empty;
};